package cn.uyunsky.platform.config.loader;

import java.io.File;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.Resource;

import cn.uyunsky.platform.config.ConfigBeanInterface;
import cn.uyunsky.platform.config.ConfigLoader;
import cn.uyunsky.platform.config.bean.menu.PlModule;
import cn.uyunsky.platform.config.bean.menu.PlTran;
import cn.uyunsky.platform.config.bean.menu.PlTree;
import cn.uyunsky.platform.config.bean.menu.TreeConfig;

public class MenuLoader implements ConfigLoader {

    private static Log log = LogFactory.getLog(MenuLoader.class);

    private static final String MENU = "/menu.xml";

    @Override
    public ConfigBeanInterface loadConfig(Resource resource,
                                          Class<? extends ConfigBeanInterface> clazz) throws Exception {
        String filepath = URLDecoder.decode(MenuLoader.class.getResource(MENU).getPath(), "utf-8");

        log.info("加载menu.xml开始,路径:" + filepath);
        File f = new File(filepath);
        TreeConfig cfg = new TreeConfig();
        // 临时容器
        Map<String, PlTran> alltran = new HashMap<String, PlTran>();
        // 临时容器
        Map<String, PlTree> treeMap = new LinkedHashMap<String, PlTree>();

        SAXReader reader = new SAXReader();
        Document doc = reader.read(f);

        // 校验没有重复tranid
        List<?> alltrans = doc.selectNodes("//tran");
        for (Object alltran1 : alltrans) {
            Element tranEle = (Element) alltran1;
            PlTran tran = getTranByElement(tranEle);
            if (alltran.containsKey(tran.getCode())) {
                throw new Exception("menu.xml 中 tran code[" + tran.getCode() + "]重复");
            } else {
                alltran.put(tran.getCode(), tran);
            }
        }

        // 加载所有节点
        Element root = doc.getRootElement();
        // 获取全部tree列表
        List<?> treeList = root.elements("tree");
        // 解析tree节点
        for (Object aTreeList : treeList) {
            // 一个tree节点
            Element treeEle = (Element) aTreeList;
            String treeid = treeEle.attributeValue("id");
            PlTree treebean = new PlTree();
            treebean.setId(treeid);
            treebean.setTreename(treeEle.attributeValue("name"));

            // 加载tree下的tran
            List<?> treeTranList = treeEle.elements("tran");
            for (Object aTreeTranList : treeTranList) {
                Element treeTranEle = (Element) aTreeTranList;
                // 添加到tree中
                treebean.addTrans(getTranByElement(treeTranEle));
            }

            // 加载tree下的Module
            List<?> treeModuleList = treeEle.elements("module");
            for (Object aTreeModuleList : treeModuleList) {
                Element treeModuleEle = (Element) aTreeModuleList;
                // 添加到tree中
                treebean.addModule(getModuleByElement(treeModuleEle));
            }
            // 将这个tree放置到容器中
            treeMap.put(treeid, treebean);
        }
        cfg.setAlltran(alltran);
        cfg.setTreeMap(treeMap);

        return cfg;
    }

    private PlModule getModuleByElement(Element element) {
        PlModule modulebean = new PlModule();
        modulebean.setId(element.attributeValue("id"));
        modulebean.setText(element.attributeValue("text"));
        modulebean.setExpanded(Boolean.parseBoolean(element.attributeValue("expanded")));

        // 先处理module下的tran
        List<?> moduleTranList = element.elements("tran");
        for (Object aModuleTranList : moduleTranList) {
            Element tranEle = (Element) aModuleTranList;
            modulebean.addTran(getTranByElement(tranEle));
        }

        // 再判断如果还是module就递归调用
        List<?> moduleMList = element.elements("module");
        for (Object aModuleMList : moduleMList) {
            Element moduleMEle = (Element) aModuleMList;
            modulebean.addModule(getModuleByElement(moduleMEle));
        }

        return modulebean;
    }

    private PlTran getTranByElement(Element tranEle) {
        PlTran tranbean = new PlTran();
        tranbean.setCode(tranEle.attributeValue("code"));
        tranbean.setText(tranEle.attributeValue("text"));
        tranbean.setUrl(tranEle.attributeValue("url"));
        return tranbean;
    }

}
